import { HttpException, Injectable } from '@nestjs/common'
import { PostsEntity } from './posts.entity'
import { InjectRepository } from '@nestjs/typeorm'
import { Like, Repository } from 'typeorm'
import * as dayjs from 'dayjs'

@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(PostsEntity)
    private readonly postsRepository: Repository<PostsEntity>
  ) {}

  /**
   * 创建文章
   */
  async create(body: Partial<PostsEntity>): Promise<PostsEntity> {
    const { title } = body
    // , content, author
    console.log('响应体', body)

    // 已经通过装饰器 - class-validator 在 DTO层实现了字段非空验证
    // if (!title) {
    //   throw new HttpException('缺少文章标题', 401)
    // }

    // if (!content) {
    //   throw new HttpException('文章内容缺失', 401)
    // }

    // if (!author) {
    //   throw new HttpException('文章作者缺失', 401)
    // }

    const doc = await this.postsRepository.findOne({
      where: {
        title
      }
    })

    if (doc) {
      throw new HttpException('文章标题重复', 401)
    }

    return await this.postsRepository.save(body)
  }

  /**
   * 分页查询所有文章
   */
  async findAll(query) {
    const { pageSize = 10, current = 1, ...rest } = query

    console.log(rest)

    const where: Partial<PostsEntity> = {}

    if ('author' in rest) {
      where.author = Like(`%${rest.author}%`) as unknown as string
    }

    if ('type' in rest) {
      where.type = rest.type
    }

    if ('thumbUrl' in rest) {
      where.thumbUrl = rest.thumbUrl
    }

    if ('content' in rest) {
      where.content = Like(`%${rest.content}%`) as unknown as string
    }

    if ('id' in rest) {
      where.id = rest.id
    }

    const res = await this.postsRepository.find({
      skip: pageSize * (current * 1 - 1),
      take: pageSize,
      // 查询条件
      where: where,

      order: {
        createTime: 'DESC'
      }
    })

    const list = res.map((item) => {
      return {
        ...item,
        createTime: dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss'),
        updateTime: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss')
      }
    })

    const allCountRes = await this.postsRepository.findAndCount({
      where: where
    })

    return {
      list: list,
      count: allCountRes[1]
    }
  }

  /**
   * 根据文章id查询详情
   */
  async getPostsById(req) {
    const { id } = req

    if (id === null) {
      throw new HttpException('文章id缺失', 401)
    }

    return await this.postsRepository.findOne({
      where: {
        id
      }
    })
  }

  /**
   * 单条删除
   * @param req
   */
  async deleteById(req) {
    const { id } = req

    if (id === null) {
      throw new HttpException('文章id缺失', 401)
    }

    const res = await this.postsRepository.findOne({
      where: {
        id
      }
    })

    if (!res) {
      throw new HttpException(`id 为${id} 文章不存在`, 401)
    }

    console.log(res)

    await this.postsRepository.remove(res)
    return {
      message: '删除成功',
      code: 200
    }
  }

  /**
   * 多条删除
   * @param req
   */
  async deleteByIds(req) {
    const { ids } = req

    if (ids === null || ids.length === 0) {
      return {
        status: 200,
        message: '请传入要删除的文章Id'
      }
    }
    console.log('要删除的ids', ids)

    await this.postsRepository.delete(ids)

    return {
      status: 200,
      messaeg: '删除成功'
    }
  }

  async update(req) {
    const { id, ...rest } = req

    if (id === null) {
      throw new HttpException('更新的文章id不存在', 401)
    }

    const hasPosts = await this.postsRepository.find(id)

    if (!hasPosts) {
      return {
        code: 200,
        message: '更新的文章不存在'
      }
    }

    if (Object.keys(rest).length === 0) {
      // 就传了一个id，其他字段都没有传的情况
      return {
        code: 200,
        message: '更新成功'
      }
    }

    const propertiesMap = this.postsRepository.metadata.propertiesMap

    // 这2个字段不能被更改
    const w = ['id', 'createTime', 'updateTime']
    const columns = Object.keys(propertiesMap).filter((key) => !w.includes(key))

    const m = {}

    // 找到要做局部更新的字段
    Object.keys(rest).forEach((key) => {
      if (columns.includes(key)) {
        m[key] = rest[key]
      }
    })

    // 实体update语法： update(第一个是查询条件，第二个对象是要更新的字段)
    await this.postsRepository.update(
      { id: id },
      {
        ...m,
        updateTime: new Date()
      }
    )

    return {
      code: 200,
      message: '修改成功'
    }
  }
}
